// 使用 ES Module 形式
import CleanWebpackPluginCModule from 'clean-webpack-plugin';
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
import HtmlWebPackPlugin from 'html-webpack-plugin';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import TerserPlugin from 'terser-webpack-plugin';
import WorkboxPlugin from 'workbox-webpack-plugin';
import path from 'path';
import { fileURLToPath } from 'url';
import Sass from 'sass';
import Fiber from 'fibers';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const { CleanWebpackPlugin } = CleanWebpackPluginCModule;

// 使用 CommonJS 形式
// const ArcGISPlugin = require('@arcgis/webpack-plugin');

// const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
// const HtmlWebPackPlugin = require('html-webpack-plugin');
// const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// const TerserPlugin = require('terser-webpack-plugin');
// const WorkboxPlugin = require('workbox-webpack-plugin');
// const path = require('path');

function resolve(dir) {
    return path.join(__dirname, '.', dir);
}

function build(env, arg) {
    const config = {
        entry: {
            index: ['./src/client/index.scss', '@babel/polyfill', './src/client/index.tsx']
        },
        output: {
            path: path.join(__dirname, 'dist'),
            chunkFilename: 'chunks/[name].[contenthash:8].js',
            publicPath: '',
            globalObject: 'this'
        },
        devtool: 'source-map',
        devServer: {
            contentBase: path.join(__dirname, 'dist'),
            compress: true,
            host: '0.0.0.0',
            port: 3001,
            writeToDisk: true,
            open: true
        },
        module: {
            rules: [
                {
                    test: /\.(ts|js)x?$/,
                    exclude: /node_modules/,
                    loader: 'babel-loader'
                },
                {
                    test: /\.tsx?$/,
                    loader: 'ts-loader',
                    options: {
                        transpileOnly: true
                    }
                },
                {
                    test: /\.html$/,
                    type: 'asset/resource',
                    exclude: /node_modules/
                },
                {
                    test: /\.(ttf|eot|svg|png|jpg|gif|ico|wsv|otf|woff(2)?)(\?[a-z0-9]+)?$/,
                    use: [
                        {
                            loader: 'file-loader'
                        }
                    ]
                },
                {
                    test: /\.css$/,
                    include: path.resolve(__dirname, 'src'),
                    exclude: /node_modules/,
                    use: [
                        {
                            loader: MiniCssExtractPlugin.loader
                        },
                        {
                            loader: 'css-loader',
                            options: {
                                modules: {
                                    localIdentName: '[name]_[local]_[hash:base64:5]'
                                },
                                importLoaders: 1,
                                modules: true
                            }
                        }
                    ]
                },
                {
                    test: /\.s[ac]ss$/i,
                    use: [
                        // 在开发过程中回退到 style-loader; 将 JS 字符串生成为 style 节点
                        arg.mode !== 'production' ? 'style-loader' : MiniCssExtractPlugin.loader,
                        // 将 CSS 转化成 CommonJS 模块
                        {
                            loader: 'css-loader',
                            options: {
                                modules: {
                                    localIdentName: '[name]_[local]_[hash:base64:5]'
                                },
                                sourceMap: true,
                                importLoaders: 1
                            }
                        },
                        {
                            // 将 Sass 编译成 CSS
                            loader: 'sass-loader',
                            options: {
                                // `dart-sass` 是首选
                                implementation: Sass,
                                sassOptions: {
                                    /**
                                     * 通常情况下同步编译的速度是异步编译速度的两倍。 为了避免这种开销，你可以使用 fibers 包从同步代码中调用异步导入程序。
                                     * https://webpack.docschina.org/loaders/sass-loader/
                                     */
                                    fiber: Fiber
                                }
                            }
                        }
                    ]
                }
            ]
        },
        optimization: {
            minimize: arg.mode === 'production',
            splitChunks: {
                chunks: 'all',
                minSize: 0,
                minChunks: 1,
                maxAsyncRequests: 30,
                maxInitialRequests: Infinity,
                automaticNameDelimiter: '~',
                enforceSizeThreshold: 50000,
                cacheGroups: {
                    defaultVendors: {
                        test: /[\\/]node_modules[\\/]/,
                        priority: -10,
                        reuseExistingChunk: true
                    },
                    default: {
                        minChunks: 2,
                        priority: -20,
                        reuseExistingChunk: true
                    }
                }
            },
            minimizer: [
                new TerserPlugin({
                    parallel: true,
                    terserOptions: {
                        compress: {
                            ecma: 5,
                            warnings: false,
                            // Disabled because of an issue with Uglify breaking seemingly valid code:
                            // https://github.com/facebook/create-react-app/issues/2376
                            // Pending further investigation:
                            // https://github.com/mishoo/UglifyJS2/issues/2011
                            comparisons: false,
                            // Disabled because of an issue with Terser breaking valid code:
                            // https://github.com/facebook/create-react-app/issues/5250
                            // Pending further investigation:
                            // https://github.com/terser-js/terser/issues/120
                            inline: 2
                        },
                        mangle: {
                            safari10: true
                        },
                        output: {
                            comments: false
                        },
                        sourceMap: arg.mode === 'development'
                    }
                }),
                new CssMinimizerPlugin()
            ],
            runtimeChunk: {
                name: 'runtime'
            }
        },
        plugins: [
            new CleanWebpackPlugin({ cleanStaleWebpackAssets: false }),

            new MiniCssExtractPlugin({
                filename: '[name].bundle.css',
                chunkFilename: '[id].css'
            }),

            // new ArcGISPlugin(),

            new HtmlWebPackPlugin({
                title: 'Aaron`s ChatRoom',
                template: './public/index.ejs',
                filename: './index.html',
                favicon: './public/favicon.ico',
                chunksSortMode: 'auto',
                inlineSource: '.(css)$',
                mode: arg.mode
            }),

            new HtmlWebPackPlugin({
                template: './public/oauth-callback.html',
                filename: './oauth-callback.html',
                chunksSortMode: 'auto',
                inject: false
            })
        ],
        resolve: {
            modules: [path.resolve(__dirname, '/src'), path.resolve(__dirname, 'node_modules/')],
            extensions: ['.ts', '.tsx', '.js', '.scss', '.css'],
            alias: {
                '@': path.resolve(__dirname ,'src')
            }
        }
    };
    if (arg.mode === 'production') {
        // config.devtool = 'source-map';
        config.devtool = false;
        config.plugins.push(
            new WorkboxPlugin.GenerateSW({
                clientsClaim: true,
                skipWaiting: true
            })
        );
    }

    return config;
}
export default build;
